package com.iagent.bean;

import com.iagent.logging.LogFactory;
import com.iagent.logging.Logger;
import com.iagent.util.CollectionUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * @author liujieyu
 * @date 2022/5/30 20:03
 * @desciption 参数集合
 */
public class IagentParamBean {

    /**
     * the parameter of Array on the method
     */
    private Class<?>[] parametersClass;

    /**
     * http url parameters index
     */
    private Map<String, Integer> paramIndex;

    /**
     * key of the url path, and args of method'annotations
     * eg: http://localhost:80/{param}
     * like Spring MVC @PathVariable("param")
     */
    private Map<String,Integer> pathIndex;

    /**
     * request header index f parameter
     */
    private Map<String, Integer> headerIndex;

    /**
     * http request body index of data
     */
    private Integer bodyIndex;


    private IagentParamBean() {
        super();;
    }

    public Class<?>[] getParametersClass() {
        return parametersClass;
    }

    public void setParametersClass(Class<?>[] parametersClass) {
        this.parametersClass = parametersClass;
    }

    public Map<String, Integer> getParamIndex() {
        return paramIndex;
    }

    public void setParamIndex(Map<String, Integer> paramIndex) {
        this.paramIndex = paramIndex;
    }

    public Map<String, Integer> getPathIndex() {
        return pathIndex;
    }

    public void setPathIndex(Map<String, Integer> pathIndex) {
        this.pathIndex = pathIndex;
    }

    public Map<String, Integer> getHeaderIndex() {
        return headerIndex;
    }

    public void setHeaderIndex(Map<String, Integer> headerIndex) {
        this.headerIndex = headerIndex;
    }

    public Integer getBodyIndex() {
        return bodyIndex;
    }

    public void setBodyIndex(Integer bodyIndex) {
        this.bodyIndex = bodyIndex;
    }

    /**
     * <b>参数建造类</b>
     */
    public static class IagentParamBeanBuilder {

        private static final Logger logger = LogFactory.getLogger(IagentParamBeanBuilder.class);

        private IagentParamBeanBuilder() {
            super();
        }

        private IagentParamBean bean = new IagentParamBean();

        public static IagentParamBeanBuilder create() {
            return new IagentParamBeanBuilder();
        }

        public IagentParamBeanBuilder setParameterClass(Class<?>[] parameterClass) {
            bean.setParametersClass(parameterClass);
            return this;
        }

        public IagentParamBeanBuilder paramIndex(String name, Integer index) {
            if (isExists(index)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("The parameter is reload, the reload parameter name is [" + name + "]");
                }
                return this;
            }
            Map<String, Integer> paramIndex = bean.getParamIndex();
            if (paramIndex == null) {
                paramIndex = new HashMap<>(4);
                paramIndex.put(name, index);
                bean.setParamIndex(paramIndex);
            } else {
                paramIndex.put(name, index);
            }
            return this;
        }

        public IagentParamBeanBuilder pathIndex(String name, Integer index) {
            if (isExists(index)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("the parameter is reload, reload paramter name is [" + name + "]");
                }
                return this;
            }
            Map<String, Integer> pathIndex = bean.getPathIndex();
            if (pathIndex == null) {
                pathIndex = new HashMap<>(4);
                pathIndex.put(name, index);
                bean.setPathIndex(pathIndex);
            } else {
                pathIndex.put(name, index);
            }
            return this;
        }

        public IagentParamBeanBuilder headerIndex(String name, Integer index) {
            if (isExists(index)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("the parameter is reload, reload paramter name is [" + name + "]");
                }
                return this;
            }
            Map<String, Integer> headerIndex = bean.getHeaderIndex();
            if (headerIndex == null) {
                headerIndex = new HashMap<>(4);
                headerIndex.put(name, index);
                bean.setHeaderIndex(headerIndex);
            } else {
                headerIndex.put(name, index);
            }
            return this;
        }

        public IagentParamBeanBuilder bodyIndex(Integer index) {
            if (isExists(index)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("the body parameter is reload");
                }
                return this;
            }
            if (bean.getBodyIndex() == null) {
                bean.setBodyIndex(index);
            } else {
                throw new IllegalArgumentException("This Body Parameter is Too Many!");
            }
            return this;
        }

        /**
         * 是否重复加载参数
         * @return
         */
        private boolean isExists(Integer index) {
            Integer bodyIndex = bean.getBodyIndex();
            Map<String, Integer> paramIndex = bean.getParamIndex();
            Map<String, Integer> headerIndex = bean.getHeaderIndex();
            Map<String, Integer> pathIndex = bean.getPathIndex();
            return (bodyIndex != null && bodyIndex.intValue() == index.intValue()) ||
                    (headerIndex != null && headerIndex.containsValue(index)) ||
                    (paramIndex != null && paramIndex.containsValue(index)) ||
                    (pathIndex != null && pathIndex.containsValue(index));
        }

        public IagentParamBean build() {
            return bean;
        }
    }
}
